﻿Imports System.Text
Imports System.IO

Public Class StripeFile
    Implements IDisposable

    Private mContentText As StringBuilder
    Private mLineItem As StringBuilder
    Private mValid As Boolean
    Private mItems() As String

    Const FileMarker As String = "<UC>"

    Enum ValueType
        SDouble = 1
        SString = 2
        SBoolean = 3
        SDateTime = 4
        SInteger = 5
        SSingle = 6
        SObject = 7
    End Enum

#Region "Get Properties"
    ReadOnly Property LineItemCount As Integer
        Get
            If mItems Is Nothing Then Return 0
            Return mItems.Count
        End Get
    End Property
    ReadOnly Property ItemsPerLineCount As Integer
        Get
            Return ParseLineItem(mItems(0)).Count
        End Get
    End Property
    ReadOnly Property GetLineItems(Index As Integer, Position As Integer) As Object
        Get
            If Index > LineItemCount - 1 Then Return Nothing
            If Position > ItemsPerLineCount - 1 Then Return Nothing

            Dim tItems() As String = mItems(Index).Split(Chr(179))
            Dim tItem As String = tItems(Position)
            Dim tType As ValueType = CInt(Strings.Right(tItem, 1))
            Dim tData As String = tItem.Substring(0, tItem.Length - 1)
            Select Case tType
                Case Is = ValueType.SBoolean
                    Return Convert.ToBoolean(tData)
                Case Is = ValueType.SInteger
                    Return Convert.ToInt32(tData)
                Case Is = ValueType.SString
                    Return tData
                Case Is = ValueType.SDateTime
                    Return Convert.ToDateTime(tData)
                Case Is = ValueType.SDouble
                    Return Convert.ToDouble(tData)
                Case Is = ValueType.SObject
                    Return ""
                Case Is = ValueType.SSingle
                    Return Convert.ToSingle(tData)
            End Select
            Return String.Empty
        End Get
    End Property
    ReadOnly Property IsStripeFile(Filename As String) As Boolean
        Get
            mValid = True
            Dim tResult = ReadFile(Filename)
            If tResult.Result <> SAEventArgs.Results.Success Then mValid = False
            Return mValid
        End Get
    End Property
#End Region
    Sub New()
        mContentText = New StringBuilder
        mLineItem = New StringBuilder
    End Sub
#Region "Add Routines"
    Sub Add(Data As Object)
        'Convert the data to string
        Dim tData As String = Convert.ToString(Data)
        'Then determine the type to add a marker
        Dim datatype = Data.GetType
        'Add the marker
        Select Case datatype
            Case Is = GetType(String)
                tData &= Convert.ToInt32(ValueType.SString)
            Case Is = GetType(Integer)
                tData &= Convert.ToInt32(ValueType.SInteger)
            Case Is = GetType(Boolean)
                tData &= Convert.ToInt32(ValueType.SBoolean)
            Case Is = GetType(Double)
                tData &= Convert.ToInt32(ValueType.SBoolean)
            Case Is = GetType(Single)
                tData &= Convert.ToInt32(ValueType.SBoolean)
            Case Is = GetType(DateTime)
                tData &= Convert.ToInt32(ValueType.SBoolean)
            Case Else
                tData = ""
                tData &= Convert.ToInt32(ValueType.SObject)
        End Select
        'First replace all chr179's with chr124s and then append chr179 - Item seperator
        tData = tData.Replace(Chr(179), Chr(124))
        'Then replace all chr232' with chr124s - New line seperator
        mLineItem.Append(tData).Append(Chr(179))
    End Sub
    Sub AddLine()
        'first remove last chr179 - New item chr
        mLineItem.Length -= 1
        'Then append chr232 - new line chr
        mContentText.Append(mLineItem).Append(Chr(232))
        mLineItem.Clear()
    End Sub
#End Region
#Region "Read and Save Data"
    Sub SaveFile(Filename As String, Compress As Boolean)
        Dim commString As String
        'Reove the last new line chr if longer than 1 chr
        If mContentText.Length > 0 Then mContentText.Length -= 1
        Using objWriter = New System.IO.StreamWriter(Filename)
            'Append <UC> - Uncompressed indicator
            commString = FileMarker & mContentText.ToString
            If Compress = True Then commString = Compression.DeflateString(commString)
            objWriter.Write(commString)
            objWriter.Close()
        End Using
    End Sub
    Function SaveDataString() As String
        Dim commString As String
        'Reove the last new line chr if longer than 1 chr
        If mContentText.Length > 0 Then mContentText.Length -= 1
        'Append <UC> - Uncompressed indicator
        commString = FileMarker & mContentText.ToString
        commString = Compression.DeflateString(commString)
        Return commString
    End Function
    Function ReadFile(Filename As String) As SAEventArgs
        If File.Exists(Filename) = False Then
            CheckData("")
            Return New SAEventArgs("File does not exists", SAEventArgs.Results.FileMissing)
        End If
        Dim commString As String
        Dim tString As String
        Using objReader As New StreamReader(Filename)
            commString = objReader.ReadToEnd
            objReader.Close()
        End Using
        tString = CheckData(commString)
        If tString = "" Then Return New SAEventArgs("Incorrect data format", SAEventArgs.Results.Undefined)
        ParseFile(tString)
        Return New SAEventArgs("", SAEventArgs.Results.Success)
    End Function
    Sub ReadDataString(Data As String)
        Dim tString As String = CheckData(Data)
        If tString = "" Then Exit Sub
        ParseFile(Data)
    End Sub
#End Region
#Region "Helper Functions"
    Function CheckData(Data As String) As String
        Dim tString As String = Strings.Left(Data, 4)
        If tString <> FileMarker Then
            Try
                Data = Compression.InflateString(Data)
                tString = Strings.Left(Data, 4)
                If tString <> FileMarker Then Throw New Exception
                mValid = True
            Catch ex As Exception
                mValid = False
                mItems = Nothing
                Data = ""
            End Try
        End If
        Return Data
    End Function
    Private Sub ParseFile(Data As String)
        'Remove the leading <UC> indicator
        Data = Data.Substring(4, Data.Length - 4)
        If Data.Trim <> "" Then mItems = Data.Split(Chr(232))
    End Sub
    Private Function ParseLineItem(Data As String) As String()
        Return Data.Split(Chr(179))
    End Function
#End Region
#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                mContentText.Clear()
                mLineItem.Clear()
            End If
        End If
        Me.disposedValue = True
    End Sub
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region
End Class
